/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "discovery/app_schema.h"
#include <gtest/gtest.h>
#include <mc/filesystem.h>
#include <test_utilities/test_base.h>

using namespace devmon;

class AppSchemaTest : public mc::test::TestWithEngine {
public:
protected:
    static void SetUpTestSuite() {
        TestWithEngine::SetUpTestSuite();
        // 初始化app_schema，添加tests_data路径以加载Component等类
        std::unordered_map<std::string, std::string> app_paths = {
            {"general_path", "opt/bmc/apps/"},
            {"test_path", "../tests/tests_data/apps/"}};
        app_schema::get_instance().init(app_paths);
    }

    static void TearDownTestSuite() {
        TestWithEngine::TearDownTestSuite();
    }

    void SetUp() override {
        TestWithEngine::SetUp();
    }

    void TearDown() override {
        TestWithEngine::TearDown();
        // 恢复SetUpTestSuite中初始化的app_schema状态
        std::unordered_map<std::string, std::string> app_paths = {
            {"general_path", "opt/bmc/apps/"},
            {"test_path", "../tests/tests_data/apps/"}};
        app_schema::get_instance().init(app_paths);
    }
};

// 测试get_class_info接口
TEST_F(AppSchemaTest, get_class_info_success) {
    mc::mutable_dict ctx;
    ctx["ChassisId"] = "1";

    auto base_info = app_schema::get_instance().get_class_info("ChassisFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Chassis/1/FruCtrl");
}

// 测试get_class_info接口， ctx中key值不区分大小写,使用全小写匹配
TEST_F(AppSchemaTest, get_class_info_success_lowercase) {
    mc::mutable_dict ctx;
    ctx["chassisid"] = "1";

    auto base_info = app_schema::get_instance().get_class_info("ChassisFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Chassis/1/FruCtrl");
}

// 测试get_class_info接口， ctx中key值不区分大小写,使用全大写匹配
TEST_F(AppSchemaTest, get_class_info_success_uppercase) {
    mc::mutable_dict ctx;
    ctx["CHASSISID"] = "1";

    auto base_info = app_schema::get_instance().get_class_info("ChassisFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Chassis/1/FruCtrl");
}

TEST_F(AppSchemaTest, get_fructrl_info_success) {
    mc::mutable_dict ctx;
    ctx["SystemId"] = "1";
    ctx["Id"]       = "2";

    auto base_info = app_schema::get_instance().get_class_info("FruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Systems/1/FruCtrl/2");
}

TEST_F(AppSchemaTest, get_childfructrl_info_success) {
    mc::mutable_dict ctx;
    ctx["parent"]  = "/bmc/kepler/Systems/1/FruCtrl/2";
    ctx["Childid"] = "1"; // 不区分大小写

    auto base_info = app_schema::get_instance().get_class_info("ChildFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Systems/1/FruCtrl/2/ChildFruCtrl/1");
}

TEST_F(AppSchemaTest, get_class_info_class_not_found) {
    mc::mutable_dict ctx;

    auto base_info = app_schema::get_instance().get_class_info("NonExistentClass", ctx);

    EXPECT_EQ(base_info.app, "");
    EXPECT_EQ(base_info.path, "");
}

TEST_F(AppSchemaTest, get_class_info_empty_context) {
    mc::mutable_dict ctx;

    auto base_info = app_schema::get_instance().get_class_info("ChassisFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Chassis/${ChassisId}/FruCtrl");
}

// 测试get_property_intf接口
TEST_F(AppSchemaTest, get_property_intf_success) {
    std::string interface1 =
        app_schema::get_instance().get_property_intf("ChassisFruCtrl", "PowerState");
    std::string interface2 =
        app_schema::get_instance().get_property_intf("ChassisFruCtrl", "PowerOnStrategy");

    EXPECT_EQ(interface1, "bmc.kepler.Chassis.FruCtrl");
    EXPECT_EQ(interface2, "bmc.kepler.Chassis.FruCtrl");
}

TEST_F(AppSchemaTest, get_property_intf_class_not_found) {
    std::string interface_name =
        app_schema::get_instance().get_property_intf("NonExistentClass", "Property1");

    EXPECT_EQ(interface_name, "");
}

TEST_F(AppSchemaTest, get_property_intf_property_not_found) {
    std::string interface_name =
        app_schema::get_instance().get_property_intf("ChassisFruCtrl", "NonExistentProperty");

    EXPECT_EQ(interface_name, "");
    EXPECT_TRUE(interface_name.empty());
}

// 测试get_property_type接口
TEST_F(AppSchemaTest, get_property_type_success) {
    std::string type1 =
        app_schema::get_instance().get_property_type("ChassisFruCtrl", "PowerState");
    std::string type2 =
        app_schema::get_instance().get_property_type("ChassisFruCtrl", "PowerOnStrategy");

    EXPECT_EQ(type1, "String");
    EXPECT_EQ(type2, "String");
}

TEST_F(AppSchemaTest, get_property_type_class_not_found) {
    std::string type =
        app_schema::get_instance().get_property_type("NonExistentClass", "PowerState");

    EXPECT_EQ(type, "");
}

TEST_F(AppSchemaTest, get_property_type_property_not_found) {
    std::string type =
        app_schema::get_instance().get_property_type("ChassisFruCtrl", "NonExistentProperty");

    EXPECT_EQ(type, "");
}

// 测试get_property_origin_name接口
TEST_F(AppSchemaTest, get_property_origin_name_success) {
    std::string origin1 =
        app_schema::get_instance().get_property_origin_name("ChassisFruCtrl", "PowerState");
    std::string origin2 =
        app_schema::get_instance().get_property_origin_name("ChassisFruCtrl", "PowerOnStrategy");

    EXPECT_EQ(origin1, "PowerStateOrigin");
    EXPECT_EQ(origin2, "");
}

TEST_F(AppSchemaTest, get_property_origin_name_property_not_found) {
    std::string origin = app_schema::get_instance().get_property_origin_name("ChassisFruCtrl",
                                                                             "NonExistentProperty");

    EXPECT_EQ(origin, "");
}

TEST_F(AppSchemaTest, get_property_origin_name_class_not_found) {
    std::string origin =
        app_schema::get_instance().get_property_origin_name("NonExistentClass", "PowerState");

    EXPECT_EQ(origin, "");
}

// 测试load方法的错误处理
TEST_F(AppSchemaTest, load_nonexistent_path) {
    // 这个测试需要直接调用load方法来测试错误处理
    std::vector<std::string> paths = {"/nonexistent/path"};

    // 应该不会抛出异常，但会记录错误日志
    EXPECT_NO_THROW(app_schema::get_instance().load(paths));
}

TEST_F(AppSchemaTest, load_file_as_directory) {
    // 创建一个文件而不是目录
    std::string file_path = "test_file.txt";
    mc::filesystem::write_file(file_path, "test content");

    std::vector<std::string> paths = {file_path};

    // 应该不会抛出异常，但会记录错误日志
    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove(file_path);
}

// 测试单例模式
TEST_F(AppSchemaTest, singleton_pattern) {
    auto& instance1 = app_schema::get_instance();
    auto& instance2 = app_schema::get_instance();

    // 应该返回同一个实例
    EXPECT_EQ(&instance1, &instance2);
}

TEST_F(AppSchemaTest, get_class_info_with_mixed_case_context) {
    mc::mutable_dict ctx;
    ctx["SystemId"] = "1";
    ctx["id"]       = "2"; // 混合大小写

    auto base_info = app_schema::get_instance().get_class_info("FruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Systems/1/FruCtrl/2");
}

TEST_F(AppSchemaTest, get_property_type_for_func_class) {
    // Func类应该返回空字符串
    std::string type = app_schema::get_instance().get_property_type("Func", "AnyProperty");

    EXPECT_EQ(type, "");
}

TEST_F(AppSchemaTest, get_property_type_with_multiple_allof_types) {
    // 测试多种类型的属性
    std::string type =
        app_schema::get_instance().get_property_type("ChassisFruCtrl", "PowerGDState");

    EXPECT_EQ(type, "U8");
}

TEST_F(AppSchemaTest, get_property_origin_name_with_title) {
    // 测试带title的属性
    std::string origin =
        app_schema::get_instance().get_property_origin_name("ChassisFruCtrl", 
                                                             "StaggeredPowerOnInterval");

    EXPECT_EQ(origin, "Name");
}

TEST_F(AppSchemaTest, get_property_origin_name_without_title) {
    // 测试不带title的属性
    std::string origin =
        app_schema::get_instance().get_property_origin_name("ChassisFruCtrl", "PowerCycleInterval");

    EXPECT_EQ(origin, "");
}

TEST_F(AppSchemaTest, get_property_intf_with_empty_interfaces) {
    // 测试空接口列表，Event类的interfaces为空对象
    std::string interface =
        app_schema::get_instance().get_property_intf("Event", "EventKeyId");

    EXPECT_EQ(interface, "");
}

TEST_F(AppSchemaTest, load_multiple_paths) {
    // 测试加载多个路径
    std::vector<std::string> paths = {"../tests/tests_data/apps/", "opt/bmc/apps/"};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));
}

TEST_F(AppSchemaTest, load_empty_paths) {
    // 测试加载空路径列表
    std::vector<std::string> paths;

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));
}

TEST_F(AppSchemaTest, init_with_multiple_app_paths) {
    // 测试init方法加载多个应用路径
    std::unordered_map<std::string, std::string> app_paths = {
        {"general_path", "../tests/tests_data/apps/"},
        {"test_path", "../tests/tests_data/apps/test_devices/"}};

    EXPECT_NO_THROW(app_schema::get_instance().init(app_paths));
}

TEST_F(AppSchemaTest, init_empty_app_paths) {
    // 测试init方法加载空路径
    std::unordered_map<std::string, std::string> app_paths;

    EXPECT_NO_THROW(app_schema::get_instance().init(app_paths));
}

TEST_F(AppSchemaTest, load_nonexistent_schema_file) {
    // 测试加载schema文件不存在的情况
    std::vector<std::string> paths = {"../tests/tests_data/apps/nonexistent_app/"};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));
}

TEST_F(AppSchemaTest, load_invalid_json_schema) {
    // 测试加载无效JSON文件
    std::string invalid_dir = "test_invalid_schema_dir";
    mc::filesystem::create_directories(invalid_dir + "/invalid_app/mds");
    mc::filesystem::write_file(invalid_dir + "/invalid_app/mds/schema.json", "invalid json content");

    std::vector<std::string> paths = {invalid_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(invalid_dir);
}

TEST_F(AppSchemaTest, load_schema_without_defs) {
    // 测试加载没有defs字段的schema
    std::string test_dir = "test_no_defs_dir";
    mc::filesystem::create_directories(test_dir + "/no_defs_app/mds");
    mc::filesystem::write_file(test_dir + "/no_defs_app/mds/schema.json", 
                                "{\"id\":\"bmc\",\"type\":\"object\"}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_object_defs) {
    // 测试加载defs不是object的schema
    std::string test_dir = "test_non_object_defs_dir";
    mc::filesystem::create_directories(test_dir + "/non_object_defs_app/mds");
    mc::filesystem::write_file(test_dir + "/non_object_defs_app/mds/schema.json", 
                                "{\"defs\":\"invalid\"}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, get_class_info_with_duplicate_keys) {
    // 测试重复的类名（应该被忽略）
    mc::mutable_dict ctx;
    ctx["SystemId"] = "1";

    auto base_info = app_schema::get_instance().get_class_info("FruCtrl", ctx);

    // 应该返回第一个加载的类的信息
    EXPECT_EQ(base_info.app, "devmon");
}

TEST_F(AppSchemaTest, get_class_info_with_complex_path) {
    // 测试复杂路径模板
    mc::mutable_dict ctx;
    ctx["parent"] = "/bmc/kepler/Systems/1/FruCtrl/2";
    ctx["ChildId"] = "3"; // 使用正确的参数名

    auto base_info = app_schema::get_instance().get_class_info("ChildFruCtrl", ctx);

    EXPECT_EQ(base_info.app, "devmon");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Systems/1/FruCtrl/2/ChildFruCtrl/3");
}

TEST_F(AppSchemaTest, get_component_class_info) {
    // 测试Component类
    mc::mutable_dict ctx;
    ctx["SystemId"] = "1";
    ctx["ID"]       = "10"; // 大写

    auto base_info = app_schema::get_instance().get_class_info("Component", ctx);

    EXPECT_EQ(base_info.app, "frudata");
    EXPECT_EQ(base_info.path, "/bmc/kepler/Systems/1/Components/10");
}

TEST_F(AppSchemaTest, get_property_type_various_types) {
    // 测试不同属性类型
    std::string type_u8 = app_schema::get_instance().get_property_type("Component", "FruId");
    std::string type_u16 = app_schema::get_instance().get_property_type("Component", "BoardId");
    std::string type_str = app_schema::get_instance().get_property_type("Component", "Name");

    EXPECT_EQ(type_u8, "U8");
    EXPECT_EQ(type_u16, "U16");
    EXPECT_EQ(type_str, "String");
}

TEST_F(AppSchemaTest, get_property_origin_name_board_node_id) {
    // 测试BoardNodeId属性的origin_name
    std::string origin =
        app_schema::get_instance().get_property_origin_name("Component", "BoardNodeId");

    EXPECT_EQ(origin, "NodeId");
}

TEST_F(AppSchemaTest, get_property_intf_with_multiple_interfaces) {
    // 测试一个属性出现在多个接口中
    std::string interface1 = app_schema::get_instance().get_property_intf("Component", "NodeId");
    std::string interface2 = app_schema::get_instance().get_property_intf("Component", "FruId");

    // NodeId可能返回bmc.kepler.Systems.Component或bmc.kepler.Systems.Board（因为unordered_map顺序不确定）
    // FruId只在bmc.kepler.Systems.Component中
    EXPECT_FALSE(interface1.empty()); // 只要不空即可
    EXPECT_EQ(interface2, "bmc.kepler.Systems.Component");
}

TEST_F(AppSchemaTest, load_schema_without_properties) {
    // 测试加载没有properties字段的schema
    std::string test_dir = "test_no_properties_dir";
    mc::filesystem::create_directories(test_dir + "/no_properties_app/mds");
    mc::filesystem::write_file(test_dir + "/no_properties_app/mds/schema.json", 
                                "{\"defs\":{\"EmptyClass\":{\"type\":\"object\"}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_without_interfaces) {
    // 测试加载没有interfaces字段的schema
    std::string test_dir = "test_no_interfaces_dir";
    mc::filesystem::create_directories(test_dir + "/no_interfaces_app/mds");
    mc::filesystem::write_file(test_dir + "/no_interfaces_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNoInterfaces\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"$ref\":\"base.json#/String\"}]}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_without_path) {
    // 测试加载没有path字段的schema
    std::string test_dir = "test_no_path_dir";
    mc::filesystem::create_directories(test_dir + "/no_path_app/mds");
    mc::filesystem::write_file(test_dir + "/no_path_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNoPath\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"$ref\":\"base.json#/String\"}]}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_string_path) {
    // 测试加载path不是string类型的schema
    std::string test_dir = "test_non_string_path_dir";
    mc::filesystem::create_directories(test_dir + "/non_string_path_app/mds");
    mc::filesystem::write_file(test_dir + "/non_string_path_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonStringPath\":{\"type\":\"object\",\"path\":123}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_object_properties) {
    // 测试加载properties不是object类型的schema
    std::string test_dir = "test_non_object_properties_dir";
    mc::filesystem::create_directories(test_dir + "/non_object_properties_app/mds");
    mc::filesystem::write_file(test_dir + "/non_object_properties_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonObjectProperties\":{\"type\":\"object\",\"properties\":\"invalid\"}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_object_interfaces) {
    // 测试加载interfaces不是object类型的schema
    std::string test_dir = "test_non_object_interfaces_dir";
    mc::filesystem::create_directories(test_dir + "/non_object_interfaces_app/mds");
    mc::filesystem::write_file(test_dir + "/non_object_interfaces_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonObjectInterfaces\":{\"type\":\"object\",\"interfaces\":\"invalid\"}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_string_interface_prop) {
    // 测试interfaces中的属性列表包含非字符串类型
    std::string test_dir = "test_non_string_interface_prop_dir";
    mc::filesystem::create_directories(test_dir + "/non_string_interface_prop_app/mds");
    mc::filesystem::write_file(test_dir + "/non_string_interface_prop_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonStringInterfaceProp\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"$ref\":\"base.json#/String\"}]}},\"interfaces\":{\"bmc.kepler.Test\":[\"Prop1\",123,\"Prop2\"]}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_missing_mds_subdirectory) {
    // 测试schema.json所在目录不存在的情况
    std::string test_dir = "test_no_mds_dir";
    mc::filesystem::create_directory(test_dir);
    mc::filesystem::create_directory(test_dir + "/no_mds_app");
    // 不创建mds目录和schema.json

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_file_is_directory) {
    // 测试schema.json是目录而不是文件的情况
    std::string test_dir = "test_schema_is_dir";
    mc::filesystem::create_directories(test_dir + "/schema_is_dir_app/mds/schema.json");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_empty_schema_file) {
    // 测试加载空文件
    std::string test_dir = "test_empty_schema_dir";
    mc::filesystem::create_directories(test_dir + "/empty_schema_app/mds");
    mc::filesystem::write_file(test_dir + "/empty_schema_app/mds/schema.json", "");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_array_allof) {
    // 测试加载allOf不是数组类型的schema
    std::string test_dir = "test_non_array_allof_dir";
    mc::filesystem::create_directories(test_dir + "/non_array_allof_app/mds");
    mc::filesystem::write_file(test_dir + "/non_array_allof_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonArrayAllOf\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":\"invalid\"}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_string_ref) {
    // 测试加载$ref不是字符串类型的schema
    std::string test_dir = "test_non_string_ref_dir";
    mc::filesystem::create_directories(test_dir + "/non_string_ref_app/mds");
    mc::filesystem::write_file(test_dir + "/non_string_ref_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonStringRef\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"$ref\":123}]}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_object_allof_item) {
    // 测试allOf中的项目不是object类型
    std::string test_dir = "test_non_object_allof_item_dir";
    mc::filesystem::create_directories(test_dir + "/non_object_allof_item_app/mds");
    mc::filesystem::write_file(test_dir + "/non_object_allof_item_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonObjectAllOfItem\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[123,\"invalid\"]}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_string_title) {
    // 测试title不是字符串类型
    std::string test_dir = "test_non_string_title_dir";
    mc::filesystem::create_directories(test_dir + "/non_string_title_app/mds");
    mc::filesystem::write_file(test_dir + "/non_string_title_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonStringTitle\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"title\":123}]}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}

TEST_F(AppSchemaTest, load_schema_with_non_array_interfaces) {
    // 测试interfaces中的属性列表不是数组类型
    std::string test_dir = "test_non_array_interfaces_dir";
    mc::filesystem::create_directories(test_dir + "/non_array_interfaces_app/mds");
    mc::filesystem::write_file(test_dir + "/non_array_interfaces_app/mds/schema.json", 
                                "{\"defs\":{\"ClassNonArrayInterfaces\":{\"type\":\"object\",\"properties\":{\"Prop1\":{\"allOf\":[{\"$ref\":\"base.json#/String\"}]}},\"interfaces\":{\"bmc.kepler.Test\":\"invalid\"}}}}}}");

    std::vector<std::string> paths = {test_dir};

    EXPECT_NO_THROW(app_schema::get_instance().load(paths));

    // 清理
    mc::filesystem::remove_all(test_dir);
}